import People
import Events
import TripExpenses
import SubGroupExpenses
import Payments
import MySQL

import numpy


class Database:
    def __init__(self):
        self.MySql = MySQL.Connection()
        self.People = People.People(self.MySql)
        self.Events= Events.Events(self.MySql)
        self.TripExpenses = TripExpenses.TripExpenses(self.MySql)
        self.SubGroupExpenses = SubGroupExpenses.SubGroupExpenses(self.MySql)
        self.Payments = Payments.Payments(self.MySql)
        
    def GetPeopleOnEvent(self, EID):
        PeopleObjs = []
        PeoplePIDs = self.Events.GetAllPeopleOnEvent(EID)
        PeopleDict = self.People.GetAllPeopleDict()
        for PID, Prop in PeoplePIDs:
            PeopleObjs.append(PeopleDict[PID])
        return PeopleObjs
        
    def GetTripExpensesOfPerson(self, EID, PID):
        ##returns[[Exp,Prop],[Exp,Prop]]
        TotalManDays = self.Events.GetTotalEventManDays(EID)
        PIDManDays = self.Events.GetPersonsManDays(EID = EID, PID = PID)
        Prop = (1.0*PIDManDays)/(TotalManDays*1.0)
        Expenses = self.TripExpenses.GetExpenses(EID=EID)
        Output = []
        for Expense in Expenses:
            Output.append([Expense, Prop])
        return Output
    
    def GetOverallSummary(self, EID, FinalCalc = None):
        Data = []
        People = self.GetPeopleOnEvent(EID)
        
        ##Trip Expenses
        TripExpenses = self.TripExpenses.GetExpenses(EID=EID)
        TripExpenseProps  = self.Events.GetAllPeopleOnEventDict(EID)
        TotalManDays = 0
        for PID in TripExpenseProps.keys():
            for Date in TripExpenseProps[PID][1]:
                TotalManDays = TotalManDays + (1.0 * (Date[1]/100.0))
        TripExpenseDict = {}
        TotalTripExpesnes = 0.0
        for Expense in TripExpenses:
            if Expense.PID not in TripExpenseDict.keys():
                TripExpenseDict[Expense.PID] = []
            TripExpenseDict[Expense.PID].append(Expense.Amount)
            TotalTripExpesnes = TotalTripExpesnes + Expense.Amount
            
            
        ##SubGroupExpenses##
        SubGroupExpenses = self.SubGroupExpenses.GetSubGroupExpenses(EID=EID)
        TotalSubGroupExpesnes = 0.0
        SubGroupExpenseDict = {}
        for Expense in SubGroupExpenses:
            if Expense.PID not in SubGroupExpenseDict.keys():
                SubGroupExpenseDict[Expense.PID] = []
            SubGroupExpenseDict[Expense.PID].append(Expense.Amount)
        SubgroupPropDict = self.SubGroupExpenses.GetSubGroupExpensePropDict(EID)
                
        
        

        
                
        for Person in People:
            Line = []
            TotalSpent = 0.0
            #Name 
            Line.append("""%s %s"""%(Person.f_Name, Person.l_Name))
            #Total Spent
            if Person.PID in TripExpenseDict.keys():
                TotalSpent = TotalSpent + numpy.sum(TripExpenseDict[Person.PID])
                
            if Person.PID in SubGroupExpenseDict.keys():
                TotalSpent = TotalSpent + numpy.sum(SubGroupExpenseDict[Person.PID])
            
            Line.append("""$ %.2f"""%(TotalSpent))
            
            
            
            ##Share of Costs
            ShareOfCosts = 0.0
            TripProp = self.Events.GetPersonsManDays(Dates = TripExpenseProps[Person.PID][1])/TotalManDays
            ShareOfCosts = TripProp * TotalTripExpesnes
            if Person.PID in SubgroupPropDict.keys():
                ShareOfCosts = ShareOfCosts + numpy.sum(SubgroupPropDict[Person.PID])
            
            
            Line.append("""$ %.2f"""%(ShareOfCosts))
            
            ##PaymentsMade
            Payments = self.Payments.GetPayments(PID = Person.PID, EID = EID)
            Made = 0.0
            for Id in Payments.keys():
                Made = Made + Payments[Id].Amount
            Line.append("""$ %.2f"""%(Made))
            
            ##Payments Recieved
            Payments = self.Payments.GetPayments(RID = Person.PID, EID = EID)
            Recieved = 0.0
            for Id in Payments.keys():
                Recieved = Recieved + Payments[Id].Amount
            Line.append("""$ %.2f"""%(Recieved))
            
            ## Total Owed/Owing
            TotalOwed = TotalSpent - ShareOfCosts - Recieved + Made
            if TotalOwed >0:
                Line.append("""$ %.2f"""%(TotalOwed))
                Line.append("""$ %.2f"""%(0.0))
            else:
                Line.append("""$ %.2f"""%(0.0))
                Line.append("""$ %.2f"""%(-1.0*TotalOwed))
                
            
            TripAccepts = self.TripExpenses.GetPersonsAccepts(Person.PID, EID)
            Status = True
            for E in TripAccepts.keys():
                if TripAccepts[E] == 0:
                    Status = False
            SGAccepts = self.SubGroupExpenses.GetAcceptState(Person.PID, EID)
            for E in SGAccepts.keys():
                if SGAccepts[E] == 0:
                    Status = False
                       
            Line.append(Status)
            if FinalCalc != None:
                FinalCalc[Person.PID] = [TotalOwed, Person, TotalOwed]
            
            
            Data.append(Line)
        return Data
        
    def GeneratePaymentMatrix(self, EventId):
        # + means money owing to that person
        ##[PID, RID, AMOUNT]
        Payments = []
        Data =  {}
        self.GetOverallSummary(EventId, Data)
        for PID in Data.keys():
            #if the person is owed money see if they have any dependants and make them pay up first
            PersonOwed = Data[PID][2]
            if PersonOwed > 0.0:    
                #Sort out Differences in Dependants First
                Deps = self.People.GetAllPersonsDeps(PID)
                for Dep in Deps:
                    if Dep in Data.keys():
                        PersonOwed = Data[PID][2]
                        Dependantowed = Data[Dep][2]
                        if Dependantowed < 0.0 and PersonOwed > 0.0:
                            # Dep owes Money and Person is still owed money
                            if PersonOwed < abs(Dependantowed):
                                #Dep owes more than PID is owed
                                # Pay the erson what they are owed
                                Payments.append([PID, Dep, PersonOwed])
                                #Update what people are owed / owing
                                Data[PID][2] = PersonOwed - PersonOwed
                                Data[Dep][2] = Dependantowed + PersonOwed
                            else:
                                #Dep can only pay a fraction of what is owed\
                                Payments.append([PID, Dep, abs(Dependantowed)])
                                Data[PID][2] = PersonOwed - abs(Dependantowed)
                                Data[Dep][2] = Dependantowed + abs(Dependantowed) # should be 0
        
        #NowRepeate for all people, making
        for PID in Data.keys():
            PersonOwed = Data[PID][2]
            # Is the person still owed money?
            if PersonOwed > 0.0:
                #Iterate Through all people 
                for TestCase in Data.keys():
                    PersonOwed = Data[PID][2]
                    TestCaseOwed = Data[TestCase][2]
                    #Does this person owe any money?
                    if TestCaseOwed < 0.0:
                        #Dep owes more than PID is owed
                        # Pay the person what they are owed
                        if PersonOwed < abs(TestCaseOwed):
                            Payments.append([PID, TestCase, PersonOwed])
                            Data[PID][2] = PersonOwed - PersonOwed
                            Data[TestCase][2] = TestCaseOwed + PersonOwed
                        else:
                            #Testcase can only pay a fraction of what is owed\
                            Payments.append([PID, TestCase, abs(TestCaseOwed)])
                            Data[PID][2] = PersonOwed - abs(TestCaseOwed)
                            Data[TestCase][2] = TestCaseOwed + abs(TestCaseOwed) # should be 0
                            
                            
        #should be done
        return [Payments, Data]
        #for Payment in Payments:
        #    print Payment
                            
            
            
            #print """ %s %s  :   $ %.2f """%(Data[PID][1].f_Name, Data[PID][1].l_Name, Data[PID][0])
            
            
    
if __name__ == '__main__':
    dB = Database()
    dB.People.AddPerson("James", "Collett", "jc")
    People = dB.People.GetAllPeopleDict()
    for Id in People.keys():
        
        print People[Id].f_Name
